# 在划分出来的组（group）上应用一些统计函数，从而达到数据分析的目的，比如对分组数据进行聚合、转换，或者过滤。这个过程主要包含以下三步：
# 拆分（Spliting）：表示对数据进行分组；
# 应用（Applying）：对分组数据应用聚合函数，进行相应计算；
# 合并（Combining）：最后汇总计算结果。

import pandas as pd
import numpy as np

data = {'Name': ['John', 'Helen', 'Sona', 'Ella'],
        'score': [82, 98, 91, 87],
        'option_course': ['C#', 'Python', 'Java', 'C']}
df = pd.DataFrame(data)
print(df)
# 创建groupby分组对象
# df.groupby("key")
# df.groupby("key",axis=1)
# df.groupby(["key1","key2"])
# 生成分组group对象
print(df.groupby('score'))  # <pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000026DB6AA9C70>
# 查看分组结果
print(df.groupby('score').groups)  # {82: [0], 87: [3], 91: [2], 98: [1]}
print(df.groupby(['Name', 'score']).groups)
# {('Ella', 87): [3], ('Helen', 98): [1], ('John', 82): [0], ('Sona', 91): [2]}
print(df.groupby('score').get_group(91))  # 根据对应组的数据值，选择一个组

# 遍历分组数据
# 查看分组
grouped = df.groupby('score')
for label, option_course in grouped:
    # 其中key代表分组后字典的键，也就是score
    print(label)
    # 字典对应的值选修的科目
    print(option_course)

# 应用一个聚合函数求均值
# print(grouped.agg(np.mean))
# 一次性应有多个聚合函数
# print(grouped['score'].agg([np.size, np.mean, np.std]))


# 组的转换操作
df = pd.DataFrame({'种类': ['水果', '水果', '水果', '蔬菜', '蔬菜', '肉类', '肉类'],
                   '产地': ['朝鲜', '中国', '缅甸', '中国', '菲律宾', '韩国', '中国'],
                   '水果': ['橘子', '苹果', '哈密瓜', '番茄', '椰子', '鱼肉', '牛肉'],
                   '数量': [3, 5, 5, 3, 2, 15, 9],
                   '价格': [2, 5, 12, 3, 4, 18, 20]})
# 分组求均值，水果、蔬菜、肉类
# 对可执行计算的数值列求均值
print(df.groupby('种类').transform(np.mean))
# transform()直接应用demean，实现去均值操作
demean = lambda arr: arr - arr.mean()
print(df.groupby('种类').transform(demean))


# 自定义函数
# 返回分组的前n行数据
def get_rows(df, n):
    # 从1到n行的所有列
    return df.iloc[:n, :]


# 分组后的组名作为行索引
print(df.groupby('种类').apply(get_rows, n=1))

# 组的数据过滤操作
# 定义lambda函数来筛选数据
print(df.groupby('Team').filter(lambda x: len(x) >= 2))
